﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace UtilZ.Dotnet.Ex.Base
{
    /// <summary>
    /// 集合扩展类
    /// </summary>
    public class CollectionEx
    {
        /// <summary>
        /// 在一个集合中查找另一个集合第一次出现的索引,找到则返回首次出现目标集合的索引，未找到则返回-1
        /// </summary>
        /// <typeparam name="T">集合项类型，必须实现IComparable接口</typeparam>
        /// <param name="source">源集合</param>
        /// <param name="offset">源集合中的起始位置</param>
        /// <param name="findLength">源集合中查找长度</param>
        /// <param name="target">要查找的目标集合</param>
        /// <returns>找到则返回首次出现目标集合的索引，未找到则返回-1</returns>
        public static int FindCollection<T>(IEnumerable<T> source, int offset, int findLength, IEnumerable<T> target) where T : IComparable
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }

            if (findLength < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(findLength));
            }

            if (offset + findLength > source.Count())
            {
                throw new ArgumentOutOfRangeException(nameof(findLength), "源集合中的起始位置+源集合中查找长度超出了源数据范围");
            }

            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            int targetCount = target.Count();
            if (targetCount == 0)
            {
                throw new ArgumentException(nameof(target), "要查找的目标集合不能为空");
            }

            int index = -1;
            if (findLength < targetCount)
            {
                return index;
            }


            /*****************************************************************
             * offset=2, findLength=20
             * 
             * 00000000 00000000 00000000 0000000 00000000 00000000 00000000
             *   ^                    ^
             * offset           offset+findLength
             *****************************************************************/

            int maxIndex = offset + findLength - targetCount + 1;
            if (maxIndex < 0)
            {
                return index;
            }

            bool flag;
            for (int i = offset; i < maxIndex; i++)
            {
                if (source.ElementAt(i).CompareTo(target.ElementAt(0)) == 0)
                {
                    flag = true;
                    for (int j = 1; j < targetCount; j++)
                    {
                        if (source.ElementAt(i + j).CompareTo(target.ElementAt(j)) != 0)
                        {
                            flag = false;
                            break;
                        }
                    }

                    if (flag)
                    {
                        index = i;
                        break;
                    }
                }
            }

            return index;
        }



    }
}
